package com.example.software.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.software.dto.MessageDTO;
import com.example.software.entity.Message;
import com.example.software.entity.Task;
import com.example.software.entity.User;
import com.example.software.mapper.MessageMapper;
import com.example.software.mapper.TaskMapper;
import com.example.software.mapper.UserMapper;
import com.example.software.service.MessageService;
import com.example.software.vo.ContactVO;
import com.example.software.vo.MessageVO;
import com.example.software.websocket.MessageWebSocketServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {
    
    private static final Logger log = LoggerFactory.getLogger(MessageServiceImpl.class);
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private TaskMapper taskMapper;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long sendMessage(MessageDTO messageDTO, Long senderId) {
        log.debug("发送消息 - 发送者ID: {}, 接收者ID: {}, 任务ID: {}", 
                senderId, messageDTO.getReceiverId(), messageDTO.getTaskId());
        
        // 验证参数
        if (messageDTO.getReceiverId() == null) {
            log.error("接收者ID为空");
            throw new RuntimeException("接收者ID不能为空");
        }
        
        if (messageDTO.getTaskId() == null) {
            log.error("任务ID为空");
            throw new RuntimeException("任务ID不能为空");
        }
        
        try {
            Message message = new Message();
            message.setSenderId(senderId);
            message.setReceiverId(messageDTO.getReceiverId());
            message.setTaskId(messageDTO.getTaskId());
            message.setContent(messageDTO.getContent());
            message.setIsRead(false);
            save(message);
            
            // 通过WebSocket通知接收者
            MessageWebSocketServer.notifyNewMessage(message);
            
            log.info("消息发送成功 - 消息ID: {}", message.getId());
            return message.getId();
        } catch (Exception e) {
            log.error("消息发送失败", e);
            throw new RuntimeException("消息发送失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<Message> getMessageList(Long userId) {
        log.debug("获取消息列表 - 用户ID: {}", userId);
        
        try {
            LambdaQueryWrapper<Message> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Message::getReceiverId, userId)
                    .or()
                    .eq(Message::getSenderId, userId);
            queryWrapper.orderByDesc(Message::getCreateTime);
            
            List<Message> messages = list(queryWrapper);
            log.info("获取到 {} 条消息", messages.size());
            return messages;
        } catch (Exception e) {
            log.error("获取消息列表失败", e);
            throw new RuntimeException("获取消息列表失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean markAsRead(Long messageId, Long userId) {
        log.debug("标记消息为已读 - 消息ID: {}, 用户ID: {}", messageId, userId);
        
        try {
            Message message = getById(messageId);
            if (message == null) {
                log.error("消息不存在 - 消息ID: {}", messageId);
                throw new RuntimeException("消息不存在");
            }
            
            // 检查是否是接收者
            if (!userId.equals(message.getReceiverId())) {
                log.error("用户不是消息接收者 - 用户ID: {}, 接收者ID: {}", userId, message.getReceiverId());
                throw new RuntimeException("只有接收者才能标记消息为已读");
            }
            
            // 已经是已读状态
            if (message.getIsRead()) {
                return true;
            }
            
            // 更新消息状态
            message.setIsRead(true);
            updateById(message);
            
            log.info("消息已标记为已读 - 消息ID: {}", messageId);
            return true;
        } catch (Exception e) {
            log.error("标记消息为已读失败", e);
            throw new RuntimeException("标记消息为已读失败: " + e.getMessage());
        }
    }
    
    @Override
    public int getUnreadMessageCount(Long userId) {
        log.debug("获取未读消息数量 - 用户ID: {}", userId);
        
        try {
            int count = baseMapper.getUnreadCount(userId);
            log.info("获取到未读消息数量: {} - 用户ID: {}", count, userId);
            return count;
        } catch (Exception e) {
            log.error("获取未读消息数量失败", e);
            throw new RuntimeException("获取未读消息数量失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<ContactVO> getContactList(Long userId) {
        log.debug("获取联系人列表 - 用户ID: {}", userId);
        
        try {
            // 获取联系人IDs
            List<Long> contactIds = baseMapper.getContactIds(userId);
            if (contactIds.isEmpty()) {
                return new ArrayList<>();
            }
            
            // 获取用户信息
            List<User> users = userMapper.selectBatchIds(contactIds);
            Map<Long, User> userMap = users.stream()
                    .collect(Collectors.toMap(User::getId, user -> user));
            
            // 构建联系人列表
            List<ContactVO> contactList = new ArrayList<>();
            
            for (Long contactId : contactIds) {
                User user = userMap.get(contactId);
                if (user == null) continue;
                
                ContactVO contact = new ContactVO();
                contact.setUserId(contactId);
                contact.setName(user.getUsername());
                contact.setUserType(user.getUserType());
                
                // 获取最新消息
                Message latestMessage = baseMapper.getLatestMessage(userId, contactId);
                if (latestMessage != null) {
                    contact.setLastMessage(latestMessage.getContent());
                    contact.setLastTime(latestMessage.getCreateTime());
                    contact.setTaskId(latestMessage.getTaskId());
                    
                    // 获取未读消息数量
                    int unreadCount = baseMapper.getUnreadCountByContact(userId, contactId);
                    contact.setUnreadCount(unreadCount);
                    
                    // 获取任务标题
                    if (latestMessage.getTaskId() != null) {
                        Task task = taskMapper.selectById(latestMessage.getTaskId());
                        if (task != null) {
                            contact.setTaskTitle(task.getTitle());
                        }
                    }
                }
                
                contactList.add(contact);
            }
            
            // 按最后消息时间排序
            contactList.sort((c1, c2) -> {
                if (c1.getLastTime() == null) return 1;
                if (c2.getLastTime() == null) return -1;
                return c2.getLastTime().compareTo(c1.getLastTime());
            });
            
            log.info("获取到联系人列表 - 数量: {}", contactList.size());
            return contactList;
        } catch (Exception e) {
            log.error("获取联系人列表失败", e);
            throw new RuntimeException("获取联系人列表失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<MessageVO> getConversation(Long userId, Long contactId) {
        log.debug("获取对话消息 - 用户ID: {}, 联系人ID: {}", userId, contactId);
        
        try {
            // 获取对话消息
            List<Message> messages = baseMapper.getConversation(userId, contactId);
            if (messages.isEmpty()) {
                return new ArrayList<>();
            }
            
            // 收集用户ID
            List<Long> userIds = new ArrayList<>();
            userIds.add(userId);
            userIds.add(contactId);
            
            // 收集任务ID
            List<Long> taskIds = messages.stream()
                    .map(Message::getTaskId)
                    .filter(id -> id != null)
                    .distinct()
                    .collect(Collectors.toList());
            
            // 获取用户信息
            Map<Long, String> usernames = new HashMap<>();
            if (!userIds.isEmpty()) {
                List<User> users = userMapper.selectBatchIds(userIds);
                for (User user : users) {
                    usernames.put(user.getId(), user.getUsername());
                }
            }
            
            // 获取任务信息
            Map<Long, String> taskTitles = new HashMap<>();
            if (!taskIds.isEmpty()) {
                List<Task> tasks = taskMapper.selectBatchIds(taskIds);
                for (Task task : tasks) {
                    taskTitles.put(task.getId(), task.getTitle());
                }
            }
            
            // 转换为VO
            List<MessageVO> messageVOs = messages.stream().map(message -> {
                MessageVO vo = new MessageVO();
                vo.setId(message.getId());
                vo.setSenderId(message.getSenderId());
                vo.setReceiverId(message.getReceiverId());
                vo.setTaskId(message.getTaskId());
                vo.setContent(message.getContent());
                vo.setIsRead(message.getIsRead());
                vo.setCreateTime(message.getCreateTime());
                
                // 设置额外信息
                vo.setSenderName(usernames.getOrDefault(message.getSenderId(), "未知用户"));
                vo.setReceiverName(usernames.getOrDefault(message.getReceiverId(), "未知用户"));
                
                if (message.getTaskId() != null) {
                    vo.setTaskTitle(taskTitles.getOrDefault(message.getTaskId(), "未知任务"));
                }
                
                return vo;
            }).collect(Collectors.toList());
            
            log.info("获取到对话消息 - 数量: {}", messageVOs.size());
            return messageVOs;
        } catch (Exception e) {
            log.error("获取对话消息失败", e);
            throw new RuntimeException("获取对话消息失败: " + e.getMessage());
        }
    }
}